package com.hxzy.service.system.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hxzy.common.enums.AckCode;
import com.hxzy.common.exception.ServiceException;
import com.hxzy.dto.system.AdminLoginDTO;
import com.hxzy.dto.system.SysUserDTO;
import com.hxzy.entity.system.SysUser;
import com.hxzy.mapper.system.SysUserMapper;
import com.hxzy.service.system.SysMenuService;
import com.hxzy.service.system.SysRoleService;
import com.hxzy.service.system.SysUserService;
import com.hxzy.vo.AdminLoginVO;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 后台用户表
 */
@Log4j2
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {


    @Autowired
    private SysRoleService sysRoleService;

    @Autowired
    private SysMenuService sysMenuService;

    @Autowired
    private RedisTemplate  redisTemplate;

    /**
     * spring security内置的
     */
    @Autowired
    private AuthenticationManager  authenticationManager;


    /**
     * 后台用户登录 （spring security的登录流程规范）
     * @param adminLoginDTO
     * @return
     */
    @Override
    public AdminLoginVO login(AdminLoginDTO adminLoginDTO) {

        //必须满足 Spring Security  AuthenticationManager类用某个方法， 实现这种规范 DaoAuthenticationProvider
        //1、创建一个spring security标准的认证的对象
        UsernamePasswordAuthenticationToken  untoken=new UsernamePasswordAuthenticationToken(adminLoginDTO.getAccount(),adminLoginDTO.getPassword());

        //2、调用spring security的登录流程，走 DaoAuthenticationProvider，自动调用 UserDetailsService接口中的方法
        Authentication  authentication= this.authenticationManager.authenticate(untoken);

        //3、判断登录是否成功
        if(authentication.isAuthenticated()){
            AdminLoginVO adminLoginVO= (AdminLoginVO) authentication.getPrincipal();
            return adminLoginVO;
        }
        return null;

    }


    /**
     * spring security的 UserDetailsServicer接口的实现方法  自定义数据库操作（查询用主呢，查询角色，查询菜单）
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        SysUser dbUser = this.baseMapper.findByAccount(username);
        if (dbUser == null) {
            log.error(username + "," + AckCode.USER_NOT_FOUND.getMsg());
            throw new ServiceException(AckCode.LOGIN_ACCOUNT_PASSWORD_ERROR);
        }

//        //取得redis的键
//        String redisKey= RedisConst.getRedisKey(RedisConst.ADMIN_LOGIN_FAILED_KEY, dbUser.getUserId()+"");
//        Object  redisValue=   this.redisTemplate.opsForValue().get(redisKey);
//        int count=0;
//        if(redisValue!=null){
//            count= (int) redisValue;
//            //不允许再登录了
//            if(count>= RedisConst.ADMIN_LOGIN_RETRY_COUNT){
//                String msg= StrUtil.format(AckCode.PASSWORD_INCRRENT_RETRY_COUNT.getMsg(), RedisConst.ADMIN_LOGIN_RETRY_COUNT+"",RedisConst.ADMIN_LOGIN_FAILED_LOCK_TIME_MINUTES+"");
//                throw new ShopException(msg);
//            }
//        }
//
//        String bcryptPwd = dbUser.getPassword();
//        if (!BCrypt.checkpw(adminLoginDTO.getPassword(), bcryptPwd)) {
//            //写入redis中的值
//            this.redisTemplate.opsForValue().increment(redisKey);
//            //设定一个过期时间
//            this.redisTemplate.expire(redisKey, RedisConst.ADMIN_LOGIN_FAILED_LOCK_TIME_MINUTES, TimeUnit.MINUTES);
//
//            //记录错误次数
//            count++;
//            if(count>= RedisConst.ADMIN_LOGIN_RETRY_COUNT){
//                String msg= StrUtil.format(AckCode.PASSWORD_INCRRENT_RETRY_COUNT.getMsg(), RedisConst.ADMIN_LOGIN_RETRY_COUNT+"",RedisConst.ADMIN_LOGIN_FAILED_LOCK_TIME_MINUTES+"");
//
//                throw new ShopException(msg);
//            }
//
//            log.error(adminLoginDTO.getAccount() + "," + AckCode.LOGIN_PASSWORD_ERROR.getMsg());
//
//            int retryCount=RedisConst.ADMIN_LOGIN_RETRY_COUNT - count;
//            String msg=StrUtil.format(AckCode.USERNAME_PASSWORD_ERROR.getMsg(), retryCount+"", RedisConst.ADMIN_LOGIN_FAILED_LOCK_TIME_MINUTES+"") ;
//            throw new ShopException(msg);
//        }

        // 状态
        String status = dbUser.getStatus();
        if (status == "1") {
            log.error(username + "," + AckCode.DEVICE_BANNED.getMsg());
            throw new ServiceException(AckCode.DEVICE_BANNED);
        }


        //自定义当前用户对象


        //自定义数据
        AdminLoginVO  adminLoginVO=new AdminLoginVO();
        adminLoginVO.setSysUser(dbUser);

        //查询该用户拥有的角色
        Set<String> roleSet= this.sysRoleService.searchUserOwnRole(dbUser.getUserId());
        adminLoginVO.setRoleSet(roleSet);

        //查询菜单角色
        Set<String> permSet=new HashSet<>();

        //判断是不是超级管理员
        if(adminLoginVO.isSuperMan()){
            permSet.add("*:*:*");
        }else{
            permSet= this.sysMenuService.searchUserOwnPerm(dbUser.getUserId());
        }
        adminLoginVO.setPermsSet(permSet);

        //返回spring security规范的对象 UserDetails
        return adminLoginVO;
    }


    /**
     * 分页查询
     * @param sysUserDTO
     * @return
     */
    @Override
    public List<SysUser> search(SysUserDTO sysUserDTO) {
        return this.baseMapper.search( sysUserDTO);
    }

}
